

import React, { Component, createRef } from 'react';
import PropTypes from 'prop-types';
import MyBtn from './MyBtn';
import EventEmitter from 'events'
/*
    组件之间的通信 
    
    1. 父子 组件 
    <A>
        <B></B>
    </A>
    2. 兄弟组件 
    <A></A>
    <B></B>

    props 传递数据
    state 修改数据 


    子组件如何修改父组件
    1. 反向 props  父组件把修改自身变量state的方法 通过 props 传递给子组件 子组件触发 

    
    兄弟组件通信
    1. 中间人模式 (父组件)  子组件A 去修改父组件  父组件再去修改 组件B 
    a. 子改父   反向props(子改父)  + props (父改子)
    b. 子改父   反向props(子改父)  + ref(父改子)


    2. 事件机制  bus 事件总线  event (emit on once)   EventBus EventEmitter  
    emit 发送事件
    on 监听事件
    once 监听一次
    remove 移除事件

    ref   this.refs  对象获取
    1. ref 作用于DOM 元素  指向这个真实的DOM元素    ref="text"  this.refs.text
    2. ref 作用于组件  指向这个组件对象             ref={e=>this.text=e }  this.text   ref={ele=>this.oh=ele}
    
    ref="text"      // this.ref.text 
    ref={ele=>this.oh=ele}   // this.oh 
    text=createRef()    //  
    this.myRef = React.createRef();     // this.myRef.current 

    ref={this.text}

    架构
    flux  redux mobx  event 

    
    受控的Input 组件
    受控的组件    input 绑定动态的 value  value 受state 状态控制的  只有state改变 input才能改变  setState 
    非受控的组件  value 没有绑定状态 
*/ 

const EventBus = new EventEmitter() 
const styles = {
    box:{
        border:'1px solid #ddd',
        borderRadius:15,
        padding:15,
        margin:15,
    }
}

class MyState2 extends Component {
    state = {
        num:1,
        flag:true,
        word:"Are you OK?"
    }

    changeNum=(num)=>{
        this.setState({
            num:this.state.num+num 
        })
    }

    changeFlag=()=>{
        this.setState({
            flag:!this.state.flag
        })
    }

    changeWord=(word)=>{
        this.setState({
            word 
        })
    }

    changeTwoMsg=()=>{
        // ref 
        this.childtwo.setState({
            msg:'努力背面试题目,多谢项目啊 '
        })
    }

    changeTwoList=()=>{
        // ref 
        this.childtwo.changeList() 
    }

    render() {
        const {num,flag,word}  = this.state;
        return (
             <div>
                {flag ? <div style={styles.box}>
                <h2>React 组件通信 (子改父 + 兄弟组件通信)</h2>
                <h2>num== {num}</h2>
                <h2>word== {word}</h2>
                
            </div> :null}
                <MyChildOne changeTwoList={this.changeTwoList}  changeTwoMsg={this.changeTwoMsg} ref={el=>this.childone=el} word={word} changeWord={this.changeWord} changeNum={this.changeNum} changeFlag={this.changeFlag} ></MyChildOne>
                <MyChildTwo  ref={el=>this.childtwo=el} num={num} word={word}  flag={flag}></MyChildTwo>
            </div> 
            
        ); 
    }
}


class MyChildOne extends Component{

    state = {

    }

    myRef=createRef()

    changeBusOne=()=>{
        console.log(this.myRef)
        this.myRef.current.style.color = "red"
        // emit 发送事件 
        EventBus.emit("changem",'Hello React')
    }

    changeTwoListByBus=()=>{
        EventBus.emit('changeTwoListByBus')
    }

    render(){
        const {changeNum , changeFlag , changeWord ,word  , changeTwoMsg , changeTwoList  } = this.props;
        return (
            <div style={styles.box}>
                <h2 ref={this.myRef} >MyChildOne - 1 - one </h2>
                <MyBtn text="changeNum" onClick={()=>changeNum(200)} ></MyBtn>
                <MyBtn text="修改flag 控制显示" onClick={changeFlag} ></MyBtn>
                <p>
                    <input type="text" value={word} ref={el=>this.inp=el}  onChange={()=>changeWord(this.inp.value)}  />
                </p>
                <MyBtn text="changeTwoMsg" onClick={changeTwoMsg} ></MyBtn>
                <MyBtn text="修改子组件two 的 list " onClick={changeTwoList} ></MyBtn>
                <MyBtn text="changeTwoMsgByBus" onClick={this.changeBusOne} ></MyBtn>
                <MyBtn text="changeTwoListByBus" onClick={this.changeTwoListByBus} ></MyBtn>
            </div>
        )
    }
}

class MyChildTwo  extends Component{
    state = {
        msg:'2217 - work hard ',
        list:['Vue',"Vue3","Webpack","Node","JS"]
    }

    // 生命周期钩子函数 
    componentDidMount(){
        // 监听事件 
        EventBus.on('changem',msg=>{
            this.setState({
                msg 
            })
        })

        // 监听一次 
        EventBus.once("changeTwoListByBus",this.changeList)
    }

    changeList=()=>{
        this.state.list.pop()
        this.setState({
            list:this.state.list 
        })
    }
    render(){
        const {num , word , flag  } = this.props
        const {msg , list } = this.state 
        return (
            <div style={styles.box}>
                <h2>MyChildTwo - 2 - two </h2>
                <h2>num = { num }   </h2>
                <h2> word = {word} </h2>
                {
                    flag && <div style={{width:200,height:200,background:'orange'}}>子组件控制我的显示和隐藏</div>
                }
                <h3>msg= {msg}</h3>
                {
                    list.map((item)=>(
                        <h3 key={item} > {item} </h3>
                    ))
                }
                <hr/>
                <MyDemo  msg="2217 - daydayup"  head={ <div>Head - Head - Haed 头部 </div> }    >
                    <h2>Hello JS</h2>
                    <h2>Hello Vue</h2>
                    <h2>Hello React</h2>
                    <h2>Hello 小程序</h2>
                    
                </MyDemo>
            </div>
        )
    }
}


// React 插槽  slot 
// 插槽 属于内容分发   父组件动态传给子租组件的内容模板 
// this.props.children 匿名插槽 
const arr = ['天长地久','九九归一','一生一世','世代相传','传宗接代']
class MyDemo extends Component {
    render(){
        console.log(this)
        const {
            msg,
            children,
            head
        } = this.props 
        return (
            <div>
                <h2>MyDemo - MyDemo - MyDemo  </h2>
                <h2>msg == {msg} </h2>
                <div>
                    {children}
                </div>
                <div>
                    {head}
                </div>
                <MyList arr={arr} >
                    {arr}
                </MyList>
            </div>
        )
    }
}


class MyList extends Component{
    render(){
        console.log(this)
        const {children} = this.props 
        return (
            <div>
                <h2> 
                    MyList - MyList -MyList
                </h2>
                {
                    children.map(item=>{
                      return   <h1 key={item} > {item}</h1>
                    })
                }
                <hr/>
                <MyLast msg={'2217'} >
                    <h2>onChange</h2>
                    <h2>onClick</h2>
                </MyLast>
            </div>
        )
    }
}

const MyLast = ({
    msg,
    children 
})=>{
    return (
        <div >
            <h2>  MyLast - MyLast - 天道酬勤  </h2>
            <h2>msg = {msg}</h2>
            <div>{children}</div>
        </div>
    )
}
export default MyState2;
